﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Greve
{
	public partial class CupRunning : Form
	{

        Thread thr;

        Object objLock = new Object();

		public	NetworkServer server;
		CupManager cup;
		List<Label> judgeNames = new System.Collections.Generic.List<Label>();
		public List<TextBox> tb = new System.Collections.Generic.List<TextBox>();
        List<Person> allPersons;

        Dictionary<Person, List<int>> completeJumpers;

        Dictionary<String, String> judgeInfo;

        int maxJudges;
        int currList = 0;
        int currentDiver = 0;
        int currentDive = 0;

        Dive currDive;
        Person currDiver;
		int port = 3000;

        private bool running = true;

		public CupRunning(CupManager man)
		{
            thr = new Thread(update);
            thr.Start();
            maxJudges = man.selectedCup.maxJudges;
            allPersons = new List<Person>();
            completeJumpers = new Dictionary<Person, List<int>>();
            judgeInfo = new Dictionary<String,String>();
			InitializeComponent();
			cup = man;
            makeJumperList();
            setCurrentDiver();
		}

		public CupRunning(CupManager man,int port)
		{
			InitializeComponent();
			cup = man;
			this.port = port;
            makeJumperList();
		}
        private void makeJumperList()
        {
            listOfJumpers.Items.Clear();
            allPersons.Clear();
            labelCurrentList.Text = cup.selectedCup.subCup[currList].name;
            for (int q = 0; q < cup.selectedCup.subCup[currList].jumpers.Count(); ++q)
            {
                listOfJumpers.Items.Add(cup.selectedCup.subCup[currList].jumpers[q].name);
                allPersons.Add(cup.selectedCup.subCup[currList].jumpers[q]);
            }
            currList++;
            if (currList > cup.selectedCup.subCup.Count)
            {
                MessageBox.Show("Cup Done", "Done");
                running = false;
            }
        }
        private void setCurrentDiver()
        {
            currDiver = allPersons[currentDiver];
            currDive = currDiver.jumps[currentDive];
            currJumper.Text = currDiver.name + " Dive " + currDive.ID+" "+ currDive.jump;
            ++currentDiver;
            if (currentDiver >= allPersons.Count)
            {
                currentDiver = 0;
                setCurrentDive();
            }
        }
        private void setCurrentDive()
        {
            currentDive++;
            if (currentDive >= cup.selectedCup.subCup[currList].maxJumps)
            {
                currentDive = 0;
                makeJumperList();
            }
        }
        private bool waitForJudges()
        {
            List<bool> doneVoting = new List<bool>();
            //while (!doneVoting && server.clientsOP.Count == maxJudges)
            {
                for (int i = 0; i < server.clientsOP.Count;++i )
                {
                    if (!tb[i].Text.Equals("-1"))
                    {
                        doneVoting.Add(true);
                    }
                    else
                        doneVoting.Add(false);
                }
            }
            if (!doneVoting.Contains(false) && server.clientsOP.Count == maxJudges)
                return true;
            else
                return false;
        }
		public void start()
		{
			server = new NetworkServer(port);
            server.chatHistory = new List<string>();
			cupName.Text = cup.selectedCup.name;
			judgeNames.Add(label2);
			judgeNames.Add(label3);
			judgeNames.Add(label4);
			judgeNames.Add(label5);
			judgeNames.Add(label6);
			judgeNames.Add(label7);
			judgeNames.Add(label8);

			tb.Add(textBox1);
			tb.Add(textBox2);
			tb.Add(textBox3);
			tb.Add(textBox4);
			tb.Add(textBox5);
			tb.Add(textBox6);
			tb.Add(textBox7);
			for (int i = 0; i < server.maxConnection; ++i)
			{
				judgeNames[judgeNames.Count - 1 - i].Hide();	// = false;
                tb[tb.Count - 1 - i].Text = "-1";
				tb[tb.Count - 1 - i].Hide(); //= false;
			}
			server.start();
		  	serverStatus.Text = server.on.ToString();
            server.runningCup = this;
		}

		private void Update_Click(object sender, EventArgs e)
		{
            updateInfo();
		}
        public void updateChatbox(String t)
        {
            
            String[] q = t.Split(' ');
            if (q[1].Equals("Values"))
            {
                lock (objLock)
                if(!judgeInfo.ContainsKey(q[0]))
                {
                    judgeInfo.Add(q[0], q[2]+ " "+ q[3] + " " + q[4]);
                }
                else
                {
                    judgeInfo[q[0]] = q[2] + " " + q[3] + " " + q[4];
                }
            }
            else
            {
                lock (objLock)
                judgeInfo.Add(q[0], "-1");
            }
            Invoke((MethodInvoker)delegate
            {
                this.chatBox.Text += "\n" + t;
                // runs on UI thread
            });
        }

        private void update()
        {
            while (running)
            {
                if (this.Created)
                {
                    Invoke((MethodInvoker)delegate
                       {
                           updateInfo();
                       });
                }
                Thread.Sleep(2000);
            }
        }

        private void CupRunning_FormClosing(object sender, FormClosingEventArgs e)
        {
            running = false;
            thr.Abort();
            thr.Join();
        }

        private void updateInfo()
        {
            int op = 0;
            foreach (var item in server.clientsOP)
            {
                this.judgeNames[op].Text = item.Value;
                this.judgeNames[op].Show();
                if (this.judgeInfo.ContainsKey(item.Value + ":"))
                {
                    this.tb[op].Text = this.judgeInfo[item.Value + ":"].Split(' ')[0];
                }
                this.tb[op].Show();
                ++op;
            }

            if (this.waitForJudges())
            {
                lock (this.objLock)
                calcScore();
                if(server.result!=null)
                    server.sendResult(cup.selectedCup.subCup[currList-1].name +"|" +currDiver.ToString());
                this.setCurrentDiver();
                List<String> nab = judgeInfo.Keys.ToList();
                foreach (String n in nab)
                {
                    this.judgeInfo[n] = "-1";
                }
            }
            this.server.send(currDiver.ToString());
        }

        private void calcScore()
        {
            double score = 0;
            List<double> currPts = new List<double>();
            double max;
            double min;
            if(maxJudges == 3)
            {
                for (int i = 0; i < 3; ++i)
                {
                    score +=(double.Parse(tb[i].Text));
                }
                currDive.score = score * currDive.difficulty;
                currDiver.totalScore += currDive.score;
            }
            if(maxJudges == 5)
            {
               
                for (int i = 0; i < 5; ++i)
                {
                    currPts.Add(double.Parse(tb[i].Text));
                }
                max = currPts.Max();
                min = currPts.Min();
                foreach(int i in currPts)
                {
                    score += i;
                }
                score -= max;
                score -= min;
                currDive.score = score * currDive.difficulty;
                currDiver.totalScore += currDive.score;
            }   
        }
	}
}
